#include "interface_fil_slaver.h"
#include <QDebug>
#include <QFileInfo>
#include <QRegExp>
interface_fil_slaver::interface_fil_slaver()
{
    // --------------------------------------------
    // 声明总线类型
    table->setItem(1-1, 1-1, new QTableWidgetItem(QString("itf_type")));
    table->setItem(1-1, 2-1, new QTableWidgetItem(QString("fil")));
    // --------------------------------------------
    // 连接从机信号到该IO
    connect(this,&interface_mdle::itf_in_rx, //主机接收信号
            this,&interface_fil_slaver::recv_itf_slot); //主机接收逻辑
}

void interface_fil_slaver::recv_itf_slot(QVariantList &itfs)
{
    if(!itfs.at(0).canConvert<itf_fil>()) //类型检查,类型不对不执行，只检查一个数据包，后续协议如果拓展，可以同时发送多个包
    {
        QDEBUG << "slaver data, and match status is " << false;
        return;
    }

    recv_fil = itfs.at(0).value<itf_fil>(); //缓存接收的结构体方便后续使用，因为信号是器件先收到，所以不需要再返回给器件
    emit recv_fil_trig(recv_fil); //IO就绪，由器件决定响应的逻辑
}

QString interface_fil_slaver::get_recv_fil_type()
{
    return QString::fromUtf8(recv_fil.type, 4);
}

void interface_fil_slaver::slaver_send_list(QStringList title)
{
    send_fil.id = 0x0;
    send_fil.size = title.count() * sizeof(quint32); //回复目录结构
    int len = sizeof(send_fil.addr) / sizeof(quint32); //获取目录级数
    for(int i = 0; i < len; i++)
    {
        send_fil.addr[i] = 0x0;
    }
    //| strcpy(send_fil.type,"list"); //确保长度为4字节,确认该方式会导致程序崩溃
    memcpy(send_fil.type,"list",4);
    send_fil.data.clear(); //重新加载数据
    bool ok; //
    QString str_data = title.join(""); // 直接将提取的所有文件头按照顺序缓存，然后直接转化为字节序发送出去
    for(int i = 0; i < str_data.length();i=i+2) //2字节转化一个16进制数
    {
        quint8 byte_hex = str_data.midRef(i,2).toUInt(&ok,16);
        if(!ok) //字符串错误
        {
            QDEBUG << "string is not hex";
            return ;
        }
        send_fil.data.append(byte_hex);
    }
    QDEBUG << title.join("").toUtf8()  << "m_fil size is:" << send_fil.size;

    //预设的指令直接触发
    QVariantList list;
    list << QVariant::fromValue(send_fil);
    emit itf_in_tx(list); //发送从机的发送信号
}
// --------------------------------------------
// 解析缓存指令
QString interface_fil_slaver::slaver_recv_save(QString basedir)
{
    QDir dir = QDir(basedir);
    if (!dir.exists())
    {
        QDEBUG << basedir << "not exist";
        return "";
    }
    QString type = QString::fromUtf8(recv_fil.type, 4); // 只处理前4个字符
    if(type != "save")
    {
        QDEBUG << basedir << "not exist";
        return "";
    }
    //解析出文件的相对路径以及文件名
    QString basename;
    int dir_len = sizeof(recv_fil.addr) / sizeof(quint32); //获取目录级数
    for(int i = 0; i < dir_len; i++)
    {
        if(recv_fil.addr[dir_len-1-i]!=0x0) //寻找第一个有效地址
        {
            QString str =  QString("%1").arg(recv_fil.addr[dir_len-1-i], 8, 16, QChar('0')).toUpper();
            basename.append(str);
            basename.append("/");
        }
    }
    QString str =  QString("%1").arg(recv_fil.id, 8, 16, QChar('0')).toUpper();
    basename.append(str);
    basename.append(".bit"); //! 嵌入式文件系统，默认都以bit为后缀
    // --------------------------------------------
    // 写入文件内容到本地的目录
    QString pns_name = dir.filePath(basename);
    QFileInfo fileInfo(pns_name);
    QString  dir_str = fileInfo.path();
    QDir dir_mk;
    dir_mk.mkdir(dir_str); //创建缓存目录
    //写入文件
    QFile file(pns_name);
    if (!file.open(QIODevice::WriteOnly)) {
        QDEBUG << "open fail:" << file.errorString();
        return "";
    }
    quint32 wr_len = file.write(recv_fil.data); //写入数据到文件
    if(wr_len != file.size())
    {
        QDEBUG << "save size not match:" << file.errorString();
    }
    file.close();

    return basename;
}

void interface_fil_slaver::slaver_send_save(QString basedir, QString basename)
{
    QDir  dir  = QDir(basedir);
    if (!dir.exists())
    {
        QDEBUG << basedir << "not exist";
    }
    QString pns_name = dir.filePath(basename);
    QFile file(pns_name); //! 获取文件
    QFileInfo info(pns_name);
    if (!file.exists()) {
        QDEBUG << pns_name << "not exist";
        return;
    }
    QString name = info.baseName(); //获取文件名，要求以8字节16进制数字表示，不然不支持
    QRegExp hexRegExp("^[0-9a-fA-F]{8}$");
    if(hexRegExp.exactMatch(name) == 0)
    {
        QDEBUG << name << "must like 00112233";
        return;
    }
    QStringList addrs = basename.split("/");
    for(int i = 0; i < addrs.size() - 1; i ++)
    {
        if(hexRegExp.exactMatch(addrs.at(i)) == 0)
        {
            QDEBUG << addrs.at(i) << "must like 00112233";
            return;
        }
        else if(addrs.at(i) == "00000000")
        {
            QDEBUG << addrs.at(i) << "cannot set 00000000";
            return;
        }
    }
    //写入文件
    file.open(QIODevice::ReadOnly);
    bool ok;
    send_fil.id = name.midRef(0,8).toUInt(&ok,16);
    send_fil.size = file.size(); //获取文件的大小
    memcpy(send_fil.type,"save",4);
    int dir_len = sizeof(recv_fil.addr) / sizeof(quint32);
    for(int i = 0; i < dir_len; i ++)
    {
        if(i < addrs.size() - 1 && addrs.size() > 1) //除了文件名外，其他目录全部加载
        {
            send_fil.addr[i] = addrs.at(addrs.size()-2-i).midRef(0,8).toUInt(&ok,16);
        }
        else
        {
            send_fil.addr[i] = 0x00000000; //结束地址
        }
    }
    send_fil.data.clear(); //无文件内容
    file.close();

    //预设的指令直接触发
    QVariantList list;
    list << QVariant::fromValue(send_fil);
    emit itf_in_tx(list); //从机发送数据

    return;
}

QString interface_fil_slaver::slaver_recv_load(QString basedir)
{
    QDir dir = QDir(basedir);
    if (!dir.exists())
    {
        QDEBUG << basedir << "not exist";
        return "";
    }
    QString type = QString::fromUtf8(recv_fil.type, 4); // 只处理前4个字符
    if(type != "load")
    {
        QDEBUG << basedir << "not exist";
        return "";
    }
    //解析出文件的相对路径以及文件名
    QString basename;
    int dir_len = sizeof(recv_fil.addr) / sizeof(quint32); //获取目录级数
    for(int i = 0; i < dir_len; i++)
    {
        if(recv_fil.addr[dir_len-1-i]!=0x0) //寻找有效地址
        {
            QString str =  QString("%1").arg(recv_fil.addr[dir_len-1-i], 8, 16, QChar('0')).toUpper();
            basename.append(str);
            basename.append("/");
        }
    }
    QString str =  QString("%1").arg(recv_fil.id, 8, 16, QChar('0')).toUpper();
    basename.append(str);
    basename.append(".bit"); //! 嵌入式文件系统，默认都以bit为后缀
    // --------------------------------------------
    // 写入文件内容到本地的目录
    QString pns_name = dir.filePath(basename);
    QFileInfo fileInfo(pns_name);
    QString  dir_str = fileInfo.path();
    QDir dir_mk;
    dir_mk.mkdir(dir_str); //创建缓存目录
    //写入文件
    QFile file(pns_name);
    if (!file.open(QIODevice::ReadOnly)) {
        QDEBUG << "open fail:" << pns_name;
        return "";
    }
    file.close();

    return basename;
}

void interface_fil_slaver::slaver_send_load(QString basedir, QString basename)
{
    QDir  dir  = QDir(basedir);
    if (!dir.exists())
    {
        QDEBUG << basedir << "not exist";
    }
    QString pns_name = dir.filePath(basename);
    QFile file(pns_name); //! 获取文件
    QFileInfo info(pns_name);
    if (!file.exists()) {
        QDEBUG << pns_name << "not exist";
        return;
    }
    QString name = info.baseName(); //获取文件名，要求以8字节16进制数字表示，不然不支持
    QRegExp hexRegExp("^[0-9a-fA-F]{8}$");
    if(hexRegExp.exactMatch(name) == 0)
    {
        QDEBUG << name << "must like 00112233";
        return;
    }
    QStringList addrs = basename.split("/");
    for(int i = 0; i < addrs.size() - 1; i ++)
    {
        if(hexRegExp.exactMatch(addrs.at(i)) == 0)
        {
            QDEBUG << addrs.at(i) << "must like 00112233";
            return;
        }
        else if(addrs.at(i) == "00000000")
        {
            QDEBUG << addrs.at(i) << "cannot set 00000000";
            return;
        }
    }
    //写入文件
    file.open(QIODevice::ReadOnly);
    bool ok;
    send_fil.id = name.midRef(0,8).toUInt(&ok,16);
    send_fil.size = file.size(); //获取文件的大小
    memcpy(send_fil.type,"load",4);
    int dir_len = sizeof(send_fil.addr) / sizeof(quint32);
    for(int i = 0; i < dir_len; i ++)
    {
        if(i < addrs.size() - 1) //除了文件名外，其他目录全部加载
        {
            send_fil.addr[i] = addrs.at(addrs.size()-2-i).midRef(0,8).toUInt(&ok,16);
        }
        else
        {
            send_fil.addr[i] = 0x00000000; //结束地址
        }
    }
    send_fil.data.clear(); //无文件内容
    send_fil.data = file.readAll(); //加载所有文件内容
    file.close();

    //预设的指令直接触发
    QVariantList list;
    list << QVariant::fromValue(send_fil);
    emit itf_in_tx(list); //从机发送数据

    return;
}
